Rework the PSCI migrate APIs
authorSoby Mathew <[email protected]>
Thu, 23 Oct 2014 09:35:34 +0000 (10:35 +0100)
committerDan Handley <[email protected]>
Mon, 26 Jan 2015 12:42:45 +0000 (12:42 +0000)
This patch reworks the PSCI MIGRATE, MIGRATE_INFO_TYPE and
MIGRATE_INFO_UP_CPU support for Trusted Firmware. The
implementation does the appropriate validation of parameters
and invokes the appropriate hook exported by the SPD.

The TSP is a MP Trusted OS. Hence the ability to actually
migrate a Trusted OS has not been implemented. The
corresponding function is not populated in the spd_pm_hooks
structure for the TSPD.

The `spd_pm_ops_t` has undergone changes with this patch.
SPD PORTS MAY NEED TO BE UPDATED.

Fixes ARM-software/tf-issues#249

Change-Id: Iabd87521bf7c530a5e4506b6d3bfd4f1bf87604f

include/bl31/services/psci.h
services/std_svc/psci/psci_common.c
services/std_svc/psci/psci_main.c
services/std_svc/psci/psci_private.h

index 3804bf2c4f8acbbb8b5b20c296369df8c5a4cbc0..de6fe4b8e86e77418c7af631ca8eeb6e98bac24b 100644 (file)
@@ -191,8 +191,8 @@ typedef struct spd_pm_ops {
        void (*svc_suspend)(uint64_t __unused);
        void (*svc_on_finish)(uint64_t __unused);
        void (*svc_suspend_finish)(uint64_t suspend_level);
-       void (*svc_migrate)(uint64_t __unused1, uint64_t __unused2);
-       int32_t (*svc_migrate_info)(uint64_t *__unused);
+       int32_t (*svc_migrate)(uint64_t from_cpu, uint64_t to_cpu);
+       int32_t (*svc_migrate_info)(uint64_t *resident_cpu);
        void (*svc_system_off)(void);
        void (*svc_system_reset)(void);
 } spd_pm_ops_t;
@@ -202,9 +202,9 @@ typedef struct spd_pm_ops {
  ******************************************************************************/
 unsigned int psci_version(void);
 int psci_affinity_info(unsigned long, unsigned int);
-int psci_migrate(unsigned int);
-unsigned int psci_migrate_info_type(void);
-unsigned long psci_migrate_info_up_cpu(void);
+int psci_migrate(unsigned long);
+int psci_migrate_info_type(void);
+long psci_migrate_info_up_cpu(void);
 int psci_cpu_on(unsigned long,
                unsigned long,
                unsigned long);
index d8c8618ff5469fd2c47185caf1510f07d9d33c05..898a343df577dee120defa2bf271c4f4c9a4b2d4 100644 (file)
@@ -561,6 +561,29 @@ void psci_register_spd_pm_hook(const spd_pm_ops_t *pm)
        psci_spd_pm = pm;
 }
 
+/*******************************************************************************
+ * This function invokes the migrate info hook in the spd_pm_ops. It performs
+ * the necessary return value validation. If the Secure Payload is UP and
+ * migrate capable, it returns the mpidr of the CPU on which the Secure payload
+ * is resident through the mpidr parameter. Else the value of the parameter on
+ * return is undefined.
+ ******************************************************************************/
+int psci_spd_migrate_info(uint64_t *mpidr)
+{
+       int rc;
+
+       if (!psci_spd_pm || !psci_spd_pm->svc_migrate_info)
+               return PSCI_E_NOT_SUPPORTED;
+
+       rc = psci_spd_pm->svc_migrate_info(mpidr);
+
+       assert(rc == PSCI_TOS_UP_MIG_CAP || rc == PSCI_TOS_NOT_UP_MIG_CAP \
+               || rc == PSCI_TOS_NOT_PRESENT_MP || rc == PSCI_E_NOT_SUPPORTED);
+
+       return rc;
+}
+
+
 /*******************************************************************************
  * This function prints the state of all affinity instances present in the
  * system
index 91d16f46a91c62804b07c1900672c8f4c4880e2a..af00551e8b21562dcac59b38eb3da54a67425054 100644 (file)
@@ -219,25 +219,57 @@ int psci_affinity_info(unsigned long target_affinity,
        return rc;
 }
 
-/* Unimplemented */
-int psci_migrate(unsigned int target_cpu)
+int psci_migrate(unsigned long target_cpu)
 {
-       return PSCI_E_NOT_SUPPORTED;
+       int rc;
+       unsigned long resident_cpu_mpidr;
+
+       rc = psci_spd_migrate_info(&resident_cpu_mpidr);
+       if (rc != PSCI_TOS_UP_MIG_CAP)
+               return (rc == PSCI_TOS_NOT_UP_MIG_CAP) ?
+                         PSCI_E_DENIED : PSCI_E_NOT_SUPPORTED;
+
+       /*
+        * Migrate should only be invoked on the CPU where
+        * the Secure OS is resident.
+        */
+       if (resident_cpu_mpidr != read_mpidr_el1())
+               return PSCI_E_NOT_PRESENT;
+
+       /* Check the validity of the specified target cpu */
+       rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
+       if (rc != PSCI_E_SUCCESS)
+               return PSCI_E_INVALID_PARAMS;
+
+       assert(psci_spd_pm && psci_spd_pm->svc_migrate);
+
+       rc = psci_spd_pm->svc_migrate(read_mpidr_el1(), target_cpu);
+       assert(rc == PSCI_E_SUCCESS || rc == PSCI_E_INTERN_FAIL);
+
+       return rc;
 }
 
-/* Unimplemented */
-unsigned int psci_migrate_info_type(void)
+int psci_migrate_info_type(void)
 {
-       return PSCI_TOS_NOT_PRESENT_MP;
+       unsigned long resident_cpu_mpidr;
+
+       return psci_spd_migrate_info(&resident_cpu_mpidr);
 }
 
-unsigned long psci_migrate_info_up_cpu(void)
+long psci_migrate_info_up_cpu(void)
 {
+       unsigned long resident_cpu_mpidr;
+       int rc;
+
        /*
-        * Return value of this currently unsupported call depends upon
-        * what psci_migrate_info_type() returns.
+        * Return value of this depends upon what
+        * psci_spd_migrate_info() returns.
         */
-       return PSCI_E_SUCCESS;
+       rc = psci_spd_migrate_info(&resident_cpu_mpidr);
+       if (rc != PSCI_TOS_NOT_UP_MIG_CAP && rc != PSCI_TOS_UP_MIG_CAP)
+               return PSCI_E_INVALID_PARAMS;
+
+       return resident_cpu_mpidr;
 }
 
 /*******************************************************************************
index 4fc87217f91cb036981cfdd442bd0af324c853a4..62477702cf50a36dd4ddaca7f6139fb7e6feaad4 100644 (file)
@@ -120,6 +120,7 @@ void psci_set_max_phys_off_afflvl(uint32_t afflvl);
 uint32_t psci_find_max_phys_off_afflvl(uint32_t start_afflvl,
                                       uint32_t end_afflvl,
                                       aff_map_node_t *mpidr_nodes[]);
+int psci_spd_migrate_info(uint64_t *mpidr);
 
 /* Private exported functions from psci_setup.c */
 int psci_get_aff_map_nodes(unsigned long mpidr,